package com.wrupple.muba.catalogs.server.service;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.jackson.map.ObjectMapper;

import com.google.inject.Inject;
import com.wrupple.muba.catalogs.server.domain.CatalogActionStateBag;
import com.wrupple.vegetate.domain.CatalogObject;
import com.wrupple.vegetate.domain.CatalogResponseContract;
import com.wrupple.vegetate.domain.exceptions.BussinessLayerException;
import com.wrupple.vegetate.domain.exceptions.CatalogException;
import com.wrupple.vegetate.domain.exceptions.DataLayerException;
import com.wrupple.vegetate.domain.exceptions.IntegrationLayerException;

public class SimpleCatalogResponseHandler implements CatalogResponseHandler {

	public static class CatalogResponseContractImpl implements
			CatalogResponseContract {

		private List<? extends CatalogObject> response;
		private String error;
		private List<String> warnings;

		public CatalogResponseContractImpl(
				List<? extends CatalogObject> response, Throwable e) {
			super();
			this.response = response;
			this.warnings = new ArrayList<String>();
			if (response == null || response.isEmpty()) {
				warnings.add(EMPTY_RESPONSE);
			}
			if (e != null) {
				this.error = e.getLocalizedMessage();
				while (e.getCause() != null) {
					e = e.getCause();
					warnings.add(e.getLocalizedMessage());
				}
			}
		}

		@Override
		public String getError() {
			return error;
		}

		@Override
		public List<? extends CatalogObject> getResponse() {
			return response;
		}

		@Override
		public List<String> getWarnings() {
			return warnings;
		}

	}

	protected final Log logger = LogFactory.getLog(getClass());
	private CatalogActionStateBag param;
	private static final String EMPTY_RESPONSE = "Empty Response";
	ObjectMapper mapper;

	@Inject
	public SimpleCatalogResponseHandler(ObjectMapper mapper) {
		super();
		this.mapper = mapper;
	}

	@Override
	public void handleResponse(HttpServletResponse resp) throws IOException,
			IntegrationLayerException {
		resp.setContentType("application/json");
		resp.setCharacterEncoding("UTF-8");
		PrintWriter out = resp.getWriter();
		String catalogid = this.param.getTargetCatalogName();
		List<CatalogObject> list = param.getCommitingResult();
		Throwable colectedException = param.getCollectedException();
		CatalogSummaryBuilder summaryBuilder = param.getSummaryBuilder();
		String callback = param.getCallbackFunctionName();
		if (summaryBuilder != null) {
			if (list != null) {
				try {
					List<CatalogObject> summaryList = summaryBuilder
							.createSummary(list, catalogid, true);
					list = summaryList;
				} catch (BussinessLayerException e) {
					colectedException = new IntegrationLayerException(
							"error building summary", e,
							CatalogException.UNSERIALIZABLE);
				} catch (DataLayerException e) {
					colectedException = new IntegrationLayerException(
							"error building summary", e,
							CatalogException.UNSERIALIZABLE);
				}
			}
		}
		CatalogResponseContractImpl response = new CatalogResponseContractImpl(
				list, colectedException);
		if (callback != null) {
			out.append(callback);
			out.append("(");
		}
		mapper.writeValue(out, response);
		if (callback != null) {
			out.append(");");
		}
		out.close();
	}

	@Override
	public void setStateBag(CatalogActionStateBag parameter) {
		this.param = parameter;
	}

}
